﻿using System;
using System.Collections.Generic;

namespace SystemWnioskujacy
{
    public class Rules
    {
        public Rule[] rTab = new Rule[0];	// TODO: Dlaczego tablica? W tym przypadku jest to nieoptymalne. Patrz metoda "Add(...)"

        public double r1 = 0.7;
        public double r2 = 0.7;
        public double t = 1.8;

        public int min_id = 0;

        public int Length
        {
            get
            {
                return rTab.Length;
            }
        }

        public Rule this[int i]
        {
            get
            {
                return rTab[i];
            }
        }

        public void Add(Rule nRule)
        {
			// TODO: Nieoptymalne. Im będzie większa tablica rTab, tym dłużej będzie trwało dodawanie nowych elementów. Czas będzię rósł wykładniczo.
            Rule[] nTab = new Rule[rTab.Length + 1];

            Array.Copy(rTab, nTab, rTab.Length);
            nTab[nTab.Length - 1] = nRule;

            rTab = nTab;
        }

        public void Remove(Rule oRule)
        {
            for (int i = 0; i < rTab.Length; i++)
            {
                if (rTab[i].Equals(oRule))
                {
                    Rule[] nTab = new Rule[rTab.Length - 1];

                    Array.Copy(rTab, nTab, i);
                    Array.Copy(rTab, i + 1, nTab, i, rTab.Length - i - 1);

                    rTab = nTab;
                    break;
                }
            }
        }

        public void Remove(int i)
        {
            if (rTab.Length > i)
            {
                Rule[] nTab = new Rule[rTab.Length - 1];

                Array.Copy(rTab, nTab, i);
                Array.Copy(rTab, i + 1, nTab, i, rTab.Length - i - 1);

                rTab = nTab;
            }
        }

        public void Run2()
        {
            Function.Println("Wnioskowanie z prawdopodobieństwem!");
            min_id = Base.FactsBase.NID;
            List<int> L = new List<int>(); // Spełniające warunki
            List<int> E = new List<int>(); // Wykonane

            for (int i = 0; i < rTab.Length; i++) if (rTab[i].grf >= r1) L.Add(i);

            while (true)
            {
                List<int> C = new List<int>(); // Rozpatrywane
                foreach (int i in L) if (!E.Contains(i) && rTab[i].Check2()) C.Add(i);

                if (C.Count > 0)
                {
                    int R = C[0];

                    foreach (int i in C) if (rTab[R].grf < rTab[i].grf) R = i;

                    Function.Println("Wybrano regułę numer " + (R + 1).ToString() + " (ID = " + R.ToString() + ").");
                    rTab[R].Execute2();
                    E.Add(R);
                }
                else break;
            }
        }

        public void Run()
        {
            for (int i = 0; i < rTab.Length; i++)
            {
                rTab[i].Check();
            }
        }

        public void Clear()
        {
            rTab = new Rule[0];
        }
    }
}
